﻿using Agility.Extensions.DatabaseAccessor;


namespace OpenAdmin.Application.Services;

/// <summary>
/// 用户服务
/// </summary>
public class AccountService : ServiceBase, IAccountService, ITransientDependency
{
    private readonly IRepository<SysUser, ApplicationDbContextLocator> _userRepository;
    private readonly IRepository<SysUserRole, ApplicationDbContextLocator> _userRoleRepository;
    private readonly IRepository<SysRole, ApplicationDbContextLocator> _roleRepository;

    private readonly IPermissionService _permissionServices;

    private readonly ITokenService _tokenService;
    /// <summary>
    /// 用户服务
    /// </summary>
    /// <param name="userRepository"></param>
    /// <param name="userRoleRepository"></param>
    /// <param name="repository"></param>
    /// <param name="permissionServices"></param>
    /// <param name="tokenService">tokenService</param>
    public AccountService(IRepository<SysUser, ApplicationDbContextLocator> userRepository,
        IRepository<SysUserRole, ApplicationDbContextLocator> userRoleRepository,
        IRepository<SysRole, ApplicationDbContextLocator> repository,
        IPermissionService permissionServices,
        ITokenService tokenService)
    {
        _userRepository = userRepository;
        _userRoleRepository = userRoleRepository;
        _roleRepository = repository;

        _permissionServices = permissionServices;

        _tokenService = tokenService;
    }
    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="requestDto"></param>
    /// <returns></returns>
    public async Task<LoginResponseDto> LoginAsync(LoginRequestDto requestDto)
    {
        var _tenantRepository = _userRepository.Change<EFCoreTenant, MultiTenancyDbContextLocator>();
        var user = await _userRepository.Entities.AsNoTracking().IgnoreQueryFilters()
            .FirstOrDefaultAsync(p => !p.IsDeleted && p.UserName == requestDto.UserName && p.Password == MD5Encryption.MD5Encrypt32(requestDto.Password));

        user.ThrowIfNull("用户不存在或密码错误!");
        user.Status.ThrowIf(p => p == 0, "您的账号已被禁用!");

        var hasSuperAdmin = user.UserType == UserType.SuperAdmin;

        var jwtPayload = new JwtPayload();
        jwtPayload.Add(ClaimTypeConsts.UserId, user.Id);
        jwtPayload.Add(TenantConstants.TENANT_KEY, user.TenantId);
        jwtPayload.Add(ClaimTypeConsts.HasSuperAdmin, hasSuperAdmin);
        var userRoles = await _userRoleRepository.Entities.Where(ur => ur.UserId == user.Id).ToListAsync();
        if (userRoles.Any())
        {
            var roleIds = userRoles.Select(ur => ur.RoleId).ToList();
            var roles = await _roleRepository.Entities.Where(r => roleIds.Contains(r.Id)).ToListAsync();
            jwtPayload.Add(ClaimTypeConsts.Role, roles.Select(r => r.Name).ToList());
        }
        //查询用户权限
        var userPermissions = await _permissionServices.GetUserPermissions(user.Id, true, hasSuperAdmin);
        jwtPayload.Add(ClaimTypeConsts.UserApiUrl, userPermissions.Select(p => p.LinkUrl).ToList());

        var tokenEntity = await _tokenService.TokenAsync(jwtPayload);

        return new LoginResponseDto
        {
            AccessToken = tokenEntity.AccessToken,
            RefreshToken = tokenEntity.RefreshToken,
            ExpiresIn = tokenEntity.ExpiresIn,
        };
    }

    /// <summary>
    /// 刷新token
    /// </summary>
    /// <param name="refreshToken"></param>
    /// <returns></returns>
    public async Task<LoginResponseDto> RefreshTokenAsync(string refreshToken)
    {
        refreshToken.ThrowIfNullOrEmpty("refreshToken无效,请重新登录!");

        var tokenEntity = await _tokenService.RefreshTokenAsync(refreshToken);

        return new LoginResponseDto
        {
            AccessToken = tokenEntity.AccessToken,
            RefreshToken = tokenEntity.RefreshToken,
            ExpiresIn = tokenEntity.ExpiresIn,
        };
    }
}
